package main

import (
	"crypto/md5"
	"encoding/xml"
	"fmt"
	"io/ioutil"
	"net/http"
	"os"
	"strings"
	"time"
)

func digest_auth(ip string, username string, password string, uri string, method string) string {
	//fmt.Println("ip:", ip)
	//fmt.Println("username:", username)
	//fmt.Println("password:", password)
	resp, err := http.Get("http://" + ip + uri)
	if err != nil {
		fmt.Println(err)
	}
	defer resp.Body.Close()
	// fmt.Println(resp.Header)
	Www_Authenticate := resp.Header.Get("WWW-Authenticate")
	//分割字符串Digest qop="auth", realm="IP Camera(C0689)", nonce="5a6a4a685a6a646c4e446b364e5759344f4459345a54413d", stale="FALSE"
	qop := strings.Split(Www_Authenticate, "qop=")[1]
	qop = strings.Split(qop, ",")[0]
	qop = strings.Replace(qop, "\"", "", -1)
	realm := strings.Split(Www_Authenticate, "realm=")[1]
	realm = strings.Split(realm, ",")[0]
	realm = strings.Replace(realm, "\"", "", -1)
	nonce := strings.Split(Www_Authenticate, "nonce=")[1]
	nonce = strings.Split(nonce, ",")[0]
	nonce = strings.Replace(nonce, "\"", "", -1)
	nc := "00000001"             //请求序号
	cnonce := "f74b7289ebe104ac" //客户端随机数
	//A1=md5(username:realm:password)
	h := md5.New()
	h.Write([]byte(username + ":" + realm + ":" + password))
	A1 := fmt.Sprintf("%x", h.Sum(nil))
	//A2=md5(method:uri)
	h.Reset()
	h.Write([]byte(method + ":" + uri))
	A2 := fmt.Sprintf("%x", h.Sum(nil))
	Authorization := ""
	//Authorization: Digest username="admin", realm="IP Camera(C0689)", nonce="5a6a4a685a6a646c4e446b364e5759344f4459345a54413d", uri="/ISAPI/Streaming/channels/33/picture", response="b3b1b5b5b3b1b5b5b3b1b5b5b3b1b5b5"
	if qop == "Undefined" {
		//response=md5(A1:nonce:A2)
		h.Reset()
		h.Write([]byte(A1 + ":" + nonce + ":" + A2))
		response := fmt.Sprintf("%x", h.Sum(nil))
		Authorization = "Digest username=\"" + username + "\", realm=\"" + realm + "\", nonce=\"" + nonce + "\", uri=\"" + uri + "\", response=\"" + response + "\""

	} else {
		//response=md5(A1:nonce:nc:cnonce:qop:A2)
		h.Reset()
		h.Write([]byte(A1 + ":" + nonce + ":" + nc + ":" + cnonce + ":" + qop + ":" + A2))
		response := fmt.Sprintf("%x", h.Sum(nil))
		//Authorization
		Authorization = "Digest username=\"" + username + "\", realm=\"" + realm + "\", nonce=\"" + nonce + "\", uri=\"" + uri + "\", response=\"" + response + "\", qop=\"" + qop + "\", nc=" + nc + ", cnonce=\"" + cnonce + "\",Basic realm=\"" + realm + "\""
	}
	// fmt.Println(Authorization)
	return Authorization
}
func digest_auth_capture(ip string, username string, password string, filePath string) string {
	uri := "/ISAPI/Streaming/channels/33/picture"
	method := "GET"
	Authorization := digest_auth(ip, username, password, uri, method)
	//设置请求头
	req, err := http.NewRequest(method, "http://"+ip+uri, nil)
	if err != nil {
		fmt.Println(err)
	}
	req.Header.Set("Authorization", Authorization)
	//发送请求
	client := &http.Client{}
	resp, err := client.Do(req)
	if err != nil {
		fmt.Println(err)
	}
	defer resp.Body.Close()
	//保存图片
	file, err := os.Create(filePath)
	if err != nil {
		fmt.Println(err)
	}
	defer file.Close()
	buf := make([]byte, 1024)
	for {
		n, err := resp.Body.Read(buf)
		if err != nil {
			break
		}
		file.Write(buf[:n])
	}
	return filePath
}
func basic_auth_capture(ip string, username string, password string, filePath string) string {
	uri := "/ISAPI/Streaming/channels/33/picture"
	method := "GET"
	//设置请求头
	req, err := http.NewRequest(method, "http://"+ip+uri, nil)
	if err != nil {
		fmt.Println(err)
	}
	req.SetBasicAuth(username, password)
	//发送请求
	client := &http.Client{}
	resp, err := client.Do(req)
	if err != nil {
		fmt.Println(err)
	}
	defer resp.Body.Close()
	//保存图片
	file, err := os.Create(filePath)
	if err != nil {
		fmt.Println(err)
	}
	defer file.Close()
	buf := make([]byte, 1024)
	for {
		n, err := resp.Body.Read(buf)
		if err != nil {
			break
		}
		file.Write(buf[:n])
	}
	return filePath
}
func set_now_to_device_time(ip string, username string, password string) {
	uri := "/ISAPI/System/time/localTime"
	method := "PUT"
	//设置请求头
	Authorization := digest_auth(ip, username, password, uri, method)
	//请求数据,格式化现行时间2018-12-12T12:12:12
	data := time.Now().Format("2006-01-02T15:04:05")
	req, err := http.NewRequest(method, "http://"+ip+uri, strings.NewReader(data))
	if err != nil {
		fmt.Println(err)
	}
	req.SetBasicAuth(username, password)
	req.Header.Set("Authorization", Authorization)
	//发送请求
	client := &http.Client{}
	resp, err := client.Do(req)
	if err != nil {
		fmt.Println(err)
	}
	defer resp.Body.Close()
	//获取请求xml数据
	body, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		fmt.Println(err)
	}
	//解析xml数据
	var result struct {
		StatusString string `xml:"statusString"`
	}
	err = xml.Unmarshal(body, &result)
	if err != nil {
		fmt.Println(err)
	}
	fmt.Println(result.StatusString)
}
func get_the_OSD(ip string, username string, password string) string {
	uri := "/ISAPI/System/Video/inputs/channels/1"
	method := "GET"
	//设置请求头
	Authorization := digest_auth(ip, username, password, uri, method)

	req, err := http.NewRequest(method, "http://"+ip+uri, nil)
	if err != nil {
		fmt.Println(err)
	}
	req.SetBasicAuth(username, password)
	req.Header.Set("Authorization", Authorization)
	//发送请求
	client := &http.Client{}
	resp, err := client.Do(req)
	if err != nil {
		fmt.Println(err)
	}
	defer resp.Body.Close()
	//获取请求xml数据
	body, err := ioutil.ReadAll(resp.Body)
	// fmt.Println(string(body))
	if err != nil {
		fmt.Println(err)
	}
	//解析xml数据
	var result struct {
		Name string `xml:"name"`
	}
	err = xml.Unmarshal(body, &result)
	if err != nil {
		fmt.Println(err)
	}
	fmt.Println(result.Name)
	return result.Name
}
func set_the_OSD_parameters(ip string, username string, password string, osd string) string {
	uri := "/ISAPI/System/Video/inputs/channels/1"
	method := "PUT"
	//设置请求头
	Authorization := digest_auth(ip, username, password, uri, method)
	//请求数据
	data := "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" +
		"<VideoInputChannel version=\"2.0\" xmlns=\"http://www.hikvision.com/ver20/XMLSchema\">" +
		"<id>1</id>" +
		"<inputPort>1</inputPort>" +
		"<name>" + osd + "</name>" +
		"<videoFormat>PAL</videoFormat>" +
		"</VideoInputChannel>"
	req, err := http.NewRequest(method, "http://"+ip+uri, strings.NewReader(data))
	if err != nil {
		fmt.Println(err)
	}
	req.SetBasicAuth(username, password)
	req.Header.Set("Authorization", Authorization)
	//发送请求
	client := &http.Client{}
	resp, err := client.Do(req)
	if err != nil {
		fmt.Println(err)
	}
	defer resp.Body.Close()
	//获取请求xml数据
	body, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		fmt.Println(err)
	}
	//解析xml数据
	var result struct {
		StatusString string `xml:"statusString"`
	}
	err = xml.Unmarshal(body, &result)
	if err != nil {
		fmt.Println(err)
	}
	fmt.Println(result.StatusString)
	return result.StatusString
}
func get_network_parameters(ip string, username string, password string) interface{} {
	uri := "/ISAPI/System/Network/interfaces"
	method := "GET"
	//设置请求头
	Authorization := digest_auth(ip, username, password, uri, method)
	req, err := http.NewRequest(method, "http://"+ip+uri, nil)
	if err != nil {
		fmt.Println(err)
	}
	req.SetBasicAuth(username, password)
	req.Header.Set("Authorization", Authorization)
	//发送请求
	client := &http.Client{}
	resp, err := client.Do(req)
	if err != nil {
		fmt.Println(err)
	}
	defer resp.Body.Close()
	//获取请求xml数据
	body, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		fmt.Println(err)
	}
	// fmt.Println(string(body))
	//解析xml数据
	var result struct {
		Interface struct {
			AddressingType string `xml:"IPAddress>addressingType"`
			IPAddr         string `xml:"IPAddress>ipAddress"`
			SubnetMask     string `xml:"IPAddress>subnetMask"`
			DefaultGateway string `xml:"IPAddress>DefaultGateway>ipAddress"`
			PrimaryDNS     string `xml:"IPAddress>PrimaryDNS>ipAddress"`
			SecondaryDNS   string `xml:"IPAddress>SecondaryDNS>ipAddress"`
		} `xml:"NetworkInterface"`
	}
	err = xml.Unmarshal(body, &result)
	if err != nil {
		fmt.Println(err)
	}
	// fmt.Println(result.Interface)
	return result.Interface

}
func set_network_parameters(ip string, username string, password string, dhcp bool, ipaddr string, subnetmask string, defaultgateway string, primarydns string, secondarydns string) string {
	uri := "/ISAPI/System/Network/interfaces/1/ipAddress"
	method := "PUT"
	//设置请求头
	Authorization := digest_auth(ip, username, password, uri, method)
	//判断dhcp是否为true
	dhcp_value := "static"
	if dhcp == true {
		dhcp_value = "dynamic"
	} else {
		dhcp_value = "static"
	}
	//请求数据
	data := `<?xml version="1.0" encoding="UTF-8"?>` +
		`<NetworkInterface><id>1</id>` +
		`<IPAddress><ipVersion>dual</ipVersion>` +
		`<addressingType>` + dhcp_value + `</addressingType>` +
		`<ipAddress>` + ipaddr + `</ipAddress>` +
		`<subnetMask>` + subnetmask + `</subnetMask>` +
		`<ipV6AddressingType>ra</ipV6AddressingType>` +
		`<DefaultGateway>` +
		`<ipAddress>` + defaultgateway + `</ipAddress>` +
		`</DefaultGateway>` +
		`<PrimaryDNS>` +
		`<ipAddress>` + primarydns + `</ipAddress>` +
		`</PrimaryDNS>` +
		`<SecondaryDNS>` +
		`<ipAddress>` + secondarydns + `</ipAddress>` +
		`</SecondaryDNS>` +
		`</IPAddress>` +
		`</NetworkInterface>`

	req, err := http.NewRequest(method, "http://"+ip+uri, strings.NewReader(data))
	if err != nil {
		fmt.Println(err)
	}
	req.SetBasicAuth(username, password)
	req.Header.Set("Authorization", Authorization)
	//发送请求
	client := &http.Client{}
	resp, err := client.Do(req)
	if err != nil {
		fmt.Println(err)
	}
	defer resp.Body.Close()
	//获取请求xml数据
	body, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		fmt.Println(err)
	}
	//解析xml数据
	var result struct {
		StatusString string `xml:"statusString"`
	}
	err = xml.Unmarshal(body, &result)
	if err != nil {
		fmt.Println(err)
	}
	fmt.Println(result.StatusString)
	return result.StatusString
}
func reboot_device(ip string, username string, password string) string {
	uri := "/ISAPI/System/reboot"
	method := "PUT"
	//设置请求头
	Authorization := digest_auth(ip, username, password, uri, method)
	req, err := http.NewRequest(method, "http://"+ip+uri, nil)
	if err != nil {
		fmt.Println(err)
	}
	req.SetBasicAuth(username, password)
	req.Header.Set("Authorization", Authorization)
	//发送请求
	client := &http.Client{}
	resp, err := client.Do(req)
	if err != nil {
		fmt.Println(err)
	}
	defer resp.Body.Close()
	//获取请求xml数据
	body, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		fmt.Println(err)
	}
	//解析xml数据
	var result struct {
		StatusString string `xml:"statusString"`
	}
	err = xml.Unmarshal(body, &result)
	if err != nil {
		fmt.Println(err)
	}
	fmt.Println(result.StatusString)
	return result.StatusString

}
func main() {
	ip := "192.168.10.148"
	username := "admin"
	password := "abc12345"
	// digest_auth_capture(ip, username, password, "test.jpg")
	// basic_auth_capture(ip, username, password, "test2.jpg")
	// set_now_to_device_time(ip, username, password)
	// set_the_OSD_parameters(ip, username, password, "测试1")
	get_the_OSD(ip, username, password)
	// detail := get_network_parameters(ip, username, password)
	// fmt.Println(detail)
	// set_network_parameters(ip, username, password, false, "192.168.10.148", "255.255.255.0", "192.168.10.1", "223.6.6.6", "8.8.8.8")
	// reboot_device(ip, username, password)
}
